<template>
    <ul class="model-attribute-choice-wrapper" ref="modelAttributeChoiceRef">
        <li v-for="(item, i) in displayList" :key="i">
            <el-tree-select
                v-model="item.model"
                :class="{ error: !item.model }"
                placeholder="请选择所属模型"
                :data="modelTree"
                :render-after-expand="false"
                :props="defaultProps"
                :filterable="true"
                :check-strictly="true"
                highlight-current
                popper-class="model-tree-select-popper"
                @change="val => onModelChange(val, item)"
            />
            <el-select
                placeholder="请选择模型属性"
                :class="{ error: !item.attribute }"
                v-model="item.attribute"
                filterable
                :disabled="!item.model"
                @change="onAttributeChange(item)"
            >
                <el-option
                    v-for="ite in filterAttribute(item.model)"
                    :key="ite.id"
                    :label="ite.displayName"
                    :value="ite.attributeName"
                />
            </el-select>
            <slot :item="item" :index="i"></slot>
            <template v-if="multiple">
                <el-button type="danger" plain size="small" :icon="Minus" circle v-if="i" @click="del(i)" />
                <template v-else>
                    <el-button type="primary" plain size="small" :icon="Plus" circle @click="add" />
                    <el-button
                        type="danger"
                        plain
                        size="small"
                        :icon="Minus"
                        circle
                        v-if="displayList.length > 1"
                        @click="del(i)"
                    />
                </template>
            </template>
        </li>
    </ul>
</template>
<script setup lang="ts">
import { modelThingService } from '@great/services';
import { Plus, Minus } from '@element-plus/icons-vue';

const props = defineProps<{
    defaultData?: Record<string, any> | Array<any> | string; // （反）显示数据
    modelDetail?: Record<string, any>; // 模型信息
    multiple?: boolean; // 是否多选
    attrRestrict?: string; // 属性限制，用于下拉选过滤（目前参考规则-触发条件类型）
}>();

const $emit = defineEmits<{
    (e: 'change', data: Array<{ model: any; attribute: any }>): void;
    (e: 'add', item: { model: any; attribute: any }): void;
    (e: 'del', index: number): void;
}>();

type DisplayList = {
    model: string;
    attribute: string;
    typeName: string;
};

const displayList = ref<Array<DisplayList>>([{ model: '', attribute: '', typeName: '' }]);
const defaultProps = {
    children: 'components',
    label: 'displayName',
    value: 'objectName'
};
const modelTree = ref<any[]>([]);
const attributeListMap = ref<Record<string, any>>({});
const modelAttributeChoiceRef = useTemplateRef('modelAttributeChoiceRef');
const del = (index: number) => {
    displayList.value.splice(index, 1);
    $emit('del', index);
};
const add = () => {
    if (modelAttributeChoiceRef.value?.querySelector('.error')) {
        ElNotification({
            message: '请完成当前选择',
            type: 'warning'
        });
    } else {
        displayList.value.push({ model: '', attribute: '', typeName: '' });
        $emit('add', { model: '', attribute: '' });
    }
};
// 属性下拉列表过滤
const filterAttribute = (objectName: string): Array<any> => {
    let targetData = JSON.parse(JSON.stringify(attributeListMap.value[objectName] || []));
    const excludeTypeName = ['Rich-Text', 'JSON', 'Lookup', 'Cascade-Lookup', 'Expression'];
    targetData = targetData.filter(item => {
        if (!excludeTypeName.includes(item.typeName)) return item;
    });
    if (props.attrRestrict == 'LENGTH_CONDITION') {
        const specialTypeName = ['Text', 'Text-Area', 'Text-Encrypeted', 'URL', 'Geolocation'];
        targetData = targetData.filter(item => specialTypeName.includes(item.typeName));
    }
    return targetData;
};
// 模型切换
const onModelChange = (objectName, row?: DisplayList) => {
    if (attributeListMap.value[objectName] && attributeListMap.value[objectName].length) {
        if (row) {
            row.attribute = '';
            $emit(
                'change',
                JSON.parse(
                    JSON.stringify({
                        ...row,
                        modelData: getModelObject(objectName, modelTree.value) || {},
                        attributeData: attributeListMap.value[objectName],
                        changeType: 'model'
                    })
                )
            );
        }
        return;
    } else {
        modelThingService.attribute
            .getList({
                objectName,
                size: 1000000
            })
            .then(result => {
                attributeListMap.value[objectName] = result.data.records || [];
                if (row) row.attribute = '';
                $emit(
                    'change',
                    JSON.parse(
                        JSON.stringify({
                            ...row,
                            modelData: getModelObject(objectName, modelTree.value) || {},
                            attributeData: attributeListMap.value[objectName],
                            changeType: 'model'
                        })
                    )
                );
            });
    }
};
// 属性切换
const onAttributeChange = (row: DisplayList) => {
    row.typeName = attributeListMap.value[row.model].find((item: any) => item.attributeName === row.attribute).typeName;
    $emit(
        'change',
        JSON.parse(
            JSON.stringify({
                ...row,
                modelData: getModelObject(row.model, modelTree.value),
                attributeData: attributeListMap.value[row.model],
                changeType: 'attribute'
            })
        )
    );
};
// 获取所选模型完整对象
const getModelObject = (objectName, findModelTree: Array<any>): any => {
    let targetModel = findModelTree.find(ite => ite.objectName == objectName);
    if (targetModel) {
        return targetModel;
    } else {
        findModelTree.some(item => {
            if (item[defaultProps.children]) {
                targetModel = getModelObject(objectName, item[defaultProps.children]);
                return targetModel ? true : false;
            }
        });
        return targetModel;
    }
};
// 获取模型属性完整选择数据
const getModelAttribute = (): Array<{ model: any; attribute: any }> => {
    const hasEmpty = displayList.value.some(item => !item.model || !item.attribute);
    if (hasEmpty) {
        ElNotification({
            message: '请完成当前选择',
            type: 'warning'
        });
        return [];
    } else {
        const targetData: Array<{ model: any; attribute: any }> = [];
        displayList.value.forEach(item => {
            if (item.model && item.attribute) {
                const targetAttribute = attributeListMap.value[item.model].find(
                    ite => ite.attributeName == item.attribute
                );
                const targetModel = getModelObject(item.model, modelTree.value);
                targetData.push({
                    model: targetModel,
                    attribute: targetAttribute
                });
            }
        });
        return JSON.parse(JSON.stringify(targetData));
    }
};
// 获取模型
const getModelTree = () => {
    if (modelTree.value && modelTree.value.length) return;
    if (props.modelDetail?.usageType == 'BUSINESS') {
        // 业务模型 （使用当前模型）
        modelTree.value = [JSON.parse(JSON.stringify(props.modelDetail))];
    } else {
        // 20251030 变更：物模型也取当前模型
        modelTree.value = [JSON.parse(JSON.stringify(props.modelDetail))];
        // modelThingService
        //     .getComponentList({
        //         objectName: props.modelDetail?.objectName
        //     })
        //     .then(result => {
        //         modelTree.value = result.data;
        //     });
    }
};
// 数据反显
const reverseDisplayData = () => {
    if (props.defaultData) {
        if (Array.isArray(props.defaultData)) {
            displayList.value = JSON.parse(JSON.stringify(props.defaultData));
        } else {
            displayList.value = [JSON.parse(JSON.stringify(props.defaultData))];
        }
        displayList.value.forEach(item => {
            onModelChange(item.model);
        });
    }
};
// 初始化
const init = () => {
    getModelTree();
    reverseDisplayData();
};
init();
defineExpose({
    getModelAttribute
});
</script>
<style scoped lang="scss">
.model-attribute-choice-wrapper {
    width: 100%;
    margin: 0;
    padding: 0;
    > li {
        list-style: none;
        display: flex;
        > .el-button {
            margin-left: 10px;
        }
        > div + div {
            margin-left: 10px;
        }
    }
    > li + li {
        margin-top: 8px;
    }
}
</style>
